﻿using System;
using System.Collections.Generic;
using System.Text;

namespace LiangHu.Net
{
    /// <summary>
    /// HttpHeader
    /// </summary>
    public class HttpHeader
    {
        Dictionary<string, KeyValuePair<string, string>> m_RequestHeaders = new Dictionary<string, KeyValuePair<string, string>>(){
            {"ACCEPT",new KeyValuePair<string,string>("Accept","*/*")},
            {"USER-AGENT",new KeyValuePair<string,string>("User-Agent","Mozilla/5.0 (Windows NT 6.1; IE 9.0)")},
            {"CONNECTION",new KeyValuePair<string,string>("Conection","Keep-Alive")}
        };
        byte[] m_Buff = null;

        /// <summary>
        /// HttpHeader
        /// </summary>
        /// <param name="httpMethod">HttpMethod</param>
        /// <param name="requestUrl">Request Uri</param>
        public HttpHeader(HttpMethod httpMethod,
            Uri requestUri)
        {
            Method = httpMethod;
            AppalyRequestUri(requestUri);
        }

        /// <summary>
        /// HttpHeader(Defualt Post Method)
        /// </summary>
        /// <param name="requestUri">Request Uri</param>
        /// <param name="bytes">Post Buff</param>
        public HttpHeader(Uri requestUri,
            byte[] bytes)
        {
            Method = HttpMethod.POST;
            AppalyRequestUri(requestUri);
            m_Buff = bytes;
        }

        /// <summary>
        /// HttpMethod
        /// </summary>
        public HttpMethod Method { get; set; }

        Uri m_RequestUri = null;
        /// <summary>
        /// Request Uri
        /// </summary>
        public Uri RequestUri
        {
            get
            {
                return m_RequestUri;
            }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value.");
                AppalyRequestUri(value);
            }
        }

        /// <summary>
        /// Cookies
        /// </summary>
        public string Cookies { get; set; }

        /// <summary>
        /// [key]
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>value</returns>
        public string this[string key]
        {
            get
            {
                string value = null, upperKey = key.ToUpper();
                switch (upperKey)
                {
                    case "URL":
                        value = RequestUri.AbsolutePath;
                        break;
                    case "HOST":
                        value = RequestUri.DnsSafeHost;
                        break;
                    case "COOKIES":
                        value = Cookies;
                        break;
                    default:
                        if (m_RequestHeaders.ContainsKey(upperKey))
                        {
                            KeyValuePair<string, string> r = m_RequestHeaders[upperKey];
                            value = r.Value;
                        }
                        break;
                }
                return value;
            }
            set
            {
                Add(key, value);
            }
        }

        void AppalyRequestUri(Uri requestUri)
        {
            if (requestUri == null)
                throw new ArgumentNullException("requestUri.");
            if (!requestUri.IsAbsoluteUri)
            {
                throw new ArgumentException("requestUrl must be an absolute url.");
            }
            m_RequestUri = requestUri;
        }

        /// <summary>
        /// Add Request Header
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        public void Add(string key, string value)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key.");
            string upperKey = key.ToUpper();
            switch (upperKey)
            {
                case "URL":
                case "HOST":
                    //ignore
                    break;
                case "COOKIES":
                    Cookies = value;
                    break;
                default:
                    KeyValuePair<string, string> r = new KeyValuePair<string, string>(key, value);
                    if (m_RequestHeaders.ContainsKey(upperKey))
                    {
                        m_RequestHeaders[upperKey] = r;
                    }
                    else
                    {
                        m_RequestHeaders.Add(upperKey, r);
                    }
                    break;
            }
        }

        /// <summary>
        /// Set Post Buff
        /// </summary>
        /// <param name="bytes">Bytes</param>
        public void SetBuff(byte[] bytes)
        {
            m_Buff = bytes;
        }

        /// <summary>
        /// ToBytes
        /// </summary>
        /// <returns>Bytes</returns>
        public byte[] ToBytes()
        {
            return Encoding.UTF8.GetBytes(ToString());
        }

        public override string ToString()
        {
            StringBuilder bulider = new StringBuilder();
            if (Method == HttpMethod.GET)
            {
                bulider.AppendLine(string.Format("GET {0} HTTP/1.1",
                  RequestUri.AbsolutePath));
            }
            else
            {
                bulider.AppendLine(string.Format("POST {0} HTTP/1.1",
                  RequestUri.AbsolutePath));
                bulider.AppendLine("Content-Type: application/x-www-form-urlencoded");
            }
            foreach (KeyValuePair<string, KeyValuePair<string, string>> r in m_RequestHeaders)
            {
                string value = r.Value.Value;
                if (!string.IsNullOrEmpty(value))
                    bulider.AppendLine(string.Format("{0}: {1}", r.Value.Key, value));
            }
            if (!string.IsNullOrEmpty(Cookies))
                bulider.AppendLine(string.Format("Cookie: {0}", Cookies));
            if (Method.Equals(HttpMethod.POST))
            {
                if (m_Buff == null)
                {
                    bulider.AppendLine("Content-Length: 0\r\n");
                }
                else
                {
                    bulider.AppendLine(string.Format("Content-Length: {0}\r\n",
                       m_Buff.Length));
                    bulider.Append(Encoding.UTF8.GetString(m_Buff));
                }
            }
            else
            {
                bulider.Append("\r\n");
            }
            return bulider.ToString();
        }
    }
}
